package com.litblue.artwork.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.litblue.api.client.GetUserInfoClient;
import com.litblue.artwork.mapper.ArtworkMapper;
import com.litblue.artwork.mapper.LitArtworkUserMapper;
import com.litblue.artwork.service.ArtworkService;
import com.litblue.artwork.task.AsyncTask;
import com.litblue.common.exception.BizIllegalException;
import com.litblue.common.utils.BeanUtils;
import com.litblue.common.utils.UserContext;
import com.litblue.starter.cache.redis.RedisCache;
import com.litblue.starter.cache.redis.RedisKeys;
import com.litblue.starter.core.AjaxResult;
import com.litblue.starter.mq.MqExChangeArtWorkInterProperties;
import com.litblue.starter.pojo.artwork.domain.LitArtworkInfo;
import com.litblue.starter.pojo.artwork.domain.LitArtworkUser;
import com.litblue.starter.pojo.artwork.dto.LitArtworkInfoDto;
import com.litblue.starter.pojo.artwork.dto.LitArtworkUserDto;
import com.litblue.starter.pojo.artwork.query.LitArtworkInfoQuery;
import com.litblue.starter.pojo.artwork.vo.LitArtworkInfoVo;
import com.litblue.starter.pojo.user.domian.LitUserInfo;
import lombok.AllArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@AllArgsConstructor
@Service
public class ArtworkServiceImpl extends ServiceImpl<ArtworkMapper, LitArtworkInfo> implements ArtworkService {

    private final RedisCache redisCache;

    private final ArtworkMapper artworkMapper;

    private final GetUserInfoClient getUserInfoClient;

    private final RabbitTemplate rabbitTemplate;

    private final AsyncTask asyncTask;




    @Override
    public AjaxResult saveArtWorkInfo(LitArtworkInfoDto litArtworkInfoDto) {
        if (litArtworkInfoDto==null){
            throw new BizIllegalException("参数为空");
        }
        if (StrUtil.isEmpty(litArtworkInfoDto.getPreviewImg())){
            throw new BizIllegalException("预览图不能为空");
        }
        litArtworkInfoDto.setUserId(UserContext.getUser());
        litArtworkInfoDto.setPublishStatus("0");
        String artworkType = litArtworkInfoDto.getArtworkType();
        if (!CollectionUtil.isEmpty(litArtworkInfoDto.getCategoryIdArray())){
            String ids = JSONUtil.toJsonStr(litArtworkInfoDto.getCategoryIdArray());
            litArtworkInfoDto.setCategoryIds(ids);
        }
        List<String> artworkImgArraySize = litArtworkInfoDto.getArtworkImgArraySize();
        if (artworkType.equals("0")){
            litArtworkInfoDto.setArtworkImgArray(JSONUtil.toJsonStr(artworkImgArraySize));
        }
        if (artworkType.equals("1")){
            if (litArtworkInfoDto.getArtworkVideo().isEmpty()) {
                throw new BizIllegalException("视频不能为空");
            }
        }
        baseMapper.insert(litArtworkInfoDto);
        redisCache.deleteKeysByPattern(RedisKeys.LIT_ALL_ARTWORK_VOS_KEY);
        return new AjaxResult("发布成功","200");
    }

    @Override
    public IPage<LitArtworkInfoVo> queryAllArtWorkData(LitArtworkInfoQuery litArtworkInfoQuery) {
        Long userId = UserContext.getUser();
        RedisKeys redisKeys = RedisKeys.forArtworkInfoVos(userId.toString(), litArtworkInfoQuery);
        Page<LitArtworkInfoVo> cacheObject = redisCache.getCacheObject(redisKeys.LIT_ARTWORK_INFO_VOS_KEY);
        if (cacheObject!=null){
            return cacheObject;
        }
        Page<LitArtworkInfoVo> pages;
        if (litArtworkInfoQuery.getPageNum()!=null&&litArtworkInfoQuery.getPageSize()!=null){
            pages = new Page<>(litArtworkInfoQuery.getPageNum(), litArtworkInfoQuery.getPageSize() );
        }
        else {
            pages =new Page<>(1,Integer.MAX_VALUE);
        }
        IPage<LitArtworkInfoVo> litArtworkInfoVoIPage = baseMapper.queryAllArtWorkData(pages, litArtworkInfoQuery);
        List<LitArtworkInfoVo> records = litArtworkInfoVoIPage.getRecords();
        Iterator<LitArtworkInfoVo> iterator = records.iterator();


//        LambdaQueryWrapper<LitArtworkInfo> wrapper = new LambdaQueryWrapper<LitArtworkInfo>();
//        wrapper.eq(LitArtworkInfo::getPublishStatus,litArtworkInfoQuery.getPublishStatus())
//                        .eq(LitArtworkInfo::getArtAuthStatus,litArtworkInfoQuery.getArtAuthStatus());
//        Page<LitArtworkInfo> litArtworkInfoPage = baseMapper.selectPage(pages, wrapper);
//        List<LitArtworkInfo> records = litArtworkInfoPage.getRecords();
//        List<LitArtworkInfoVo> litArtworkInfoVos = BeanUtils.copyList(records, LitArtworkInfoVo.class);
//        Iterator<LitArtworkInfoVo> iterator = litArtworkInfoVos.iterator();
        ArrayList<CompletableFuture<Void>> completableFutures = new ArrayList<>();
        while (iterator.hasNext()){
            LitArtworkInfoVo artworkInfoVo = iterator.next();
            Long userId1 = artworkInfoVo.getUserId();
            LitUserInfo userInfo = getUserInfoClient.queryUserInfo(userId1);
            artworkInfoVo.setLitUserInfo(userInfo);
            String artworkImgArray = artworkInfoVo.getArtworkImgArray();
            if (StrUtil.isNotEmpty(artworkImgArray)){
                List<String> strings = JSON.parseArray(artworkImgArray, String.class);
                artworkInfoVo.setArtworkImgArraySize(strings);
            }
            CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
                Future<Integer> likeCount = asyncTask.jobGetLikeCountTask(artworkInfoVo.getId(), "0");
                Future<Integer> favoriteCount = asyncTask.jobGetLikeCountTask(artworkInfoVo.getId(), "1");
                Future<Boolean> isLike = asyncTask.jobGetIsLike(userId, artworkInfoVo.getId(), "0");
                Future<Boolean> isFavorite = asyncTask.jobGetIsLike(userId, artworkInfoVo.getId(), "1");
                try {
                    artworkInfoVo.setLikeNums(likeCount.get());
                    artworkInfoVo.setFavoritesNums(favoriteCount.get());
                    artworkInfoVo.setIsLike(isLike.get());
                    artworkInfoVo.setIsFavorites(isFavorite.get());
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (ExecutionException e) {
                    throw new RuntimeException(e);
                }
            });
            completableFutures.add(voidCompletableFuture);
        }
        CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).join();
//        Page<LitArtworkInfoVo> returnPage = new Page<LitArtworkInfoVo>(litArtworkInfoQuery.getPageNum(), litArtworkInfoQuery.getPageSize()).setRecords(litArtworkInfoVos);
//        returnPage.setTotal(litArtworkInfoPage.getTotal()-litArtworkInfoQuery.getPageNum()*litArtworkInfoQuery.getPageSize());
        redisCache.setCacheObject(redisKeys.LIT_ARTWORK_INFO_VOS_KEY,litArtworkInfoVoIPage);

        return litArtworkInfoVoIPage;
    }

    /**
     * 处理点赞或收藏艺术品信息的操作
     *
     * @param litArtworkUserDto 包含艺术品信息和操作类型的DTO
     * @return 返回操作结果的AjaxResult对象
     */
    @Override
    public AjaxResult clickLikeArtInfo(LitArtworkUserDto litArtworkUserDto) {
        // 获取当前用户信息
        Long user = UserContext.getUser();
        // 将当前用户的ID设置到DTO中
        litArtworkUserDto.setUserId(user);

        // 删除所有艺术品信息的缓存，因为艺术品的点赞/收藏状态已改变
        redisCache.deleteKeysByPattern(RedisKeys.LIT_ALL_ARTWORK_VOS_KEY);

        // 生成特定艺术品信息的Redis键，并删除对应缓存
        RedisKeys redisKeys = RedisKeys.forArtworkInfo(user.toString(), litArtworkUserDto.getArtworkId().toString());
        redisCache.deleteObject(redisKeys.LIT_ARTWORK_INFO_KEY);

        // 根据操作类型选择对应的前缀键
        String keyFix = litArtworkUserDto.getOperateType().equals("0") ? "LIKE_PREFIX" : "FAVORITE_PREFIX";

        // 生成用户点赞/收藏艺术品的Redis键
        RedisKeys clickAddKey = RedisKeys.forArtworkUser(litArtworkUserDto, keyFix);

        // 检查并获取Redis中对应点赞/收藏操作的艺术品信息
        LitArtworkUserDto litArtworkInfoDto1 = redisCache.getCacheObject(clickAddKey.LIT_ARTWORK_USER_KEY);

        // 如果找到对应的信息，说明用户已经点赞/收藏过，需要删除
        if (ObjectUtil.isNotEmpty(litArtworkInfoDto1)){
            redisCache.deleteObject(clickAddKey.LIT_ARTWORK_USER_KEY);
            // 发送消息到MQ，通知取消点赞/收藏操作
            rabbitTemplate.convertAndSend(MqExChangeArtWorkInterProperties.DIRECT_ARTWORK,MqExChangeArtWorkInterProperties.ROUTING_ARTWORK_KEY_REMOVE,litArtworkInfoDto1);
            return new AjaxResult<>("删除成功","200");
        }

        // 没找到对应的信息，说明是新的点赞/收藏操作，保存到Redis
        redisCache.setCacheObject(clickAddKey.LIT_ARTWORK_USER_KEY,litArtworkUserDto);
        // 发送消息到MQ，通知新增点赞/收藏操作
        rabbitTemplate.convertAndSend(MqExChangeArtWorkInterProperties.DIRECT_ARTWORK,MqExChangeArtWorkInterProperties.ROUTING_ARTWORK_KEY_ADD,litArtworkUserDto);

        return new AjaxResult<>("success","200");
    }

    @Override
    public AjaxResult getLitArtworkInfoVo(Long artworkId) {
        Long userId = UserContext.getUser();
        RedisKeys redisKeys = RedisKeys.forArtworkInfo(userId.toString(), artworkId.toString());
        LitArtworkInfoVo cacheObject = redisCache.getCacheObject(redisKeys.LIT_ARTWORK_INFO_KEY);
        if (ObjectUtil.isNotEmpty(cacheObject)){
            return new AjaxResult("success","200",cacheObject);
        }
        LitArtworkInfo litArtworkInfo = artworkMapper.selectById(artworkId);
        if (litArtworkInfo==null){
            throw new BizIllegalException("未找到信息");
        }
        LitArtworkInfoVo artworkInfoVo = BeanUtils.copyBean(litArtworkInfo, LitArtworkInfoVo.class);

        LitUserInfo userInfo = getUserInfoClient.queryUserInfo(userId);
        artworkInfoVo.setLitUserInfo(userInfo);
        String artworkImgArray = artworkInfoVo.getArtworkImgArray();
        if (StrUtil.isNotEmpty(artworkImgArray)){
            List<String> strings = JSON.parseArray(artworkImgArray, String.class);
            artworkInfoVo.setArtworkImgArraySize(strings);
        }
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            Future<Integer> likeCount = asyncTask.jobGetLikeCountTask(artworkInfoVo.getId(), "0");
            Future<Integer> favoriteCount = asyncTask.jobGetLikeCountTask(artworkInfoVo.getId(), "1");
            Future<Boolean> isLike = asyncTask.jobGetIsLike(userId, artworkInfoVo.getId(), "0");
            Future<Boolean> isFavorite = asyncTask.jobGetIsLike(userId, artworkInfoVo.getId(), "1");
            try {
                artworkInfoVo.setLikeNums(likeCount.get());
                artworkInfoVo.setFavoritesNums(favoriteCount.get());
                artworkInfoVo.setIsLike(isLike.get());
                artworkInfoVo.setIsFavorites(isFavorite.get());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
        });
        CompletableFuture.allOf(voidCompletableFuture).join();
        redisCache.setCacheObject(redisKeys.LIT_ARTWORK_INFO_KEY,artworkInfoVo,5, TimeUnit.MINUTES);
        return new AjaxResult<>("success","200",artworkInfoVo);
    }
}
